﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.IO;

using OpenCvSharp;
using OpenCvSharp.MachineLearning;
using OpenCvSharp.Blob;
using OpenCvSharp.UserInterface;
using OpenCvSharp.CPlusPlus;
using System.Xml;
using System.Xml.Serialization;




namespace RecognitionNumbers
{
    public partial class Form1 : Form
    {
        public НастройкиПоискНомера настройкиПоискНомера;
        public НастройкиПоискаСимволов настройкиПоискСимволов;
        public Image исходноеИзображение;
        public SearchRectangle поискПрямоугольника;
        public SearchSymbol поискСимволов;
        public List<MatrixSymbol> матрицыСимволов;
        public Capture capture;
        public Motion motion;
        public List<Number> History;
        public List<Number> last;
        public List<int> sh;

        [DllImport("avicap32.dll")]
       
        protected static extern bool capGetDriverDescriptionA(short wDriverIndex, [MarshalAs(UnmanagedType.VBByRefStr)] ref String lpszName, int cbName, [MarshalAs(UnmanagedType.VBByRefStr)] ref String lpszVer, int cbVer);


        public Form1()
        {
            InitializeComponent();
            настройкиПоискНомера = new НастройкиПоискНомера();
            настройкиПоискСимволов = new НастройкиПоискаСимволов();
            History = new List<Number>();
            XmlSerializer xml;
            FileStream stream;
            if (File.Exists("НастройкиПоискНомера.xml"))
            {
                xml = new XmlSerializer(typeof(НастройкиПоискНомера));
                stream = new FileStream("НастройкиПоискНомера.xml", FileMode.Open, FileAccess.Read);
                настройкиПоискНомера = (НастройкиПоискНомера)xml.Deserialize(stream);
                stream.Close();
            }
            else
            {
                настройкиПоискНомера.название = "Поиск номера";
                настройкиПоискНомера.описание = "Поиск изображения на фото которое может быть номерным знаком";
                настройкиПоискНомера.порогБинаризации = 125;
                настройкиПоискНомера.процентЦветных = 20;
                настройкиПоискНомера.процентЧерногоВерх = 80;
                настройкиПоискНомера.процентЧерногоНиз = 20;
                настройкиПоискНомера.соотношениеСторон = 2.5;
                настройкиПоискНомера.отклонениеСторон = 20;
            }

            if (File.Exists("НастройкиПоискаСимволов.xml"))
            {
                xml = new XmlSerializer(typeof(НастройкиПоискаСимволов));
                stream = new FileStream("НастройкиПоискаСимволов.xml", FileMode.Open, FileAccess.Read);
                настройкиПоискСимволов = (НастройкиПоискаСимволов)xml.Deserialize(stream);
                stream.Close();
            }
            else
            {
                настройкиПоискСимволов.название = "Поиск символов";
                настройкиПоискСимволов.описание = "Поиск изображения на фото которое может быть символом номерного знака";
                настройкиПоискСимволов.порогБинаризации = 125;
                настройкиПоискСимволов.отклонениеРазмер = 100;
                настройкиПоискСимволов.радиус = 1;
                настройкиПоискСимволов.размер = 1;
                настройкиПоискСимволов.соотношениеСторон = 0.8;
                настройкиПоискСимволов.отклонениеСторон = 20;
            }
            if (File.Exists("Матрицы.xml"))
            {
                xml = new XmlSerializer(typeof(List<MatrixSymbol>));
                stream = new FileStream("Матрицы.xml", FileMode.Open, FileAccess.Read);
                матрицыСимволов = (List<MatrixSymbol>)xml.Deserialize(stream);
                stream.Close();
            }
            else
            {
                матрицыСимволов = new List<MatrixSymbol>();
                char[] lN = { 'А', 'В', 'Е', 'К', 'М', 'Н', 'О', 'Р', 'С', 'Т', 'У', 'Х', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
                foreach (char t in lN)
                {
                    MatrixSymbol m = new MatrixSymbol();
                    m.symbol = t;
                    m.clear();
                    матрицыСимволов.Add(m);
                }
            }

            if (File.Exists("Истрия.xml"))
            {
                xml = new XmlSerializer(typeof(List<Number>));
                stream = new FileStream("Истрия.xml", FileMode.Open, FileAccess.Read);
                History = (List<Number>)xml.Deserialize(stream);
                stream.Close();
            }
           


           

        }

        private void fotoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SearchAndRecognition s = new SearchAndRecognition(настройкиПоискНомера, настройкиПоискСимволов, матрицыСимволов);
            openFotoDialog.ShowDialog();

            if (File.Exists(openFotoDialog.FileName))
            {
                исходноеИзображение = new Image(openFotoDialog.FileName);
                List<Number> l = s.go(исходноеИзображение, обучетьToolStripMenuItem.Checked);
                if ((l.Count > 0) )
                {
                    foreach (Number k in l)
                        History.Add(k);

                    if (l[0].numeber != null)
                    {
                        
                        label1.Text = l[0].text;
                        pictureBox2.Image = l[0].numeber.ToBitmap();
                        pictureBox3.Image = l[0].sybol.ToBitmap();
                        label1.Visible = true;
                        pictureBox1.Image = s.output.ToBitmap();
                    }
                }
            }
            showHistory();
        }

        private void фильтрыToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Обработка(исходноеИзображение);
            Фильтры фильтры = new Фильтры(this);
            фильтры.Show();
        }

        public void Обработка(Image исходнаКартинка)
        {
            toolStripStatusLabel2.Text = "";
            DateTime time = DateTime.Now;
            поискПрямоугольника = new SearchRectangle(исходнаКартинка.image, настройкиПоискНомера.порогБинаризации, настройкиПоискНомера.процентЦветных, настройкиПоискНомера.процентЧерногоНиз, настройкиПоискНомера.процентЧерногоВерх, настройкиПоискНомера.соотношениеСторон, настройкиПоискНомера.отклонениеСторон);
            toolStripStatusLabel2.Text = "Номер найден за " + Convert.ToString((DateTime.Now - time).TotalSeconds) + "c ";
            pictureBox1.Image = null;
            pictureBox1.Image = поискПрямоугольника.output.ToBitmap();
            pictureBox1.Refresh();
            if (поискПрямоугольника.coordinatesRectangle.Count >= 1)
                
                foreach (IplImage p in поискПрямоугольника.imageRectangle)
                {
                    поискСимволов = new SearchSymbol(p, настройкиПоискСимволов.порогБинаризации, настройкиПоискСимволов.радиус, настройкиПоискСимволов.размер, настройкиПоискСимволов.отклонениеРазмер, настройкиПоискСимволов.соотношениеСторон, настройкиПоискСимволов.отклонениеСторон);
                    if (поискСимволов.coordinatesRectangle.Count >= 5)
                    {
                        /*if (обучетьToolStripMenuItem.Checked)
                        {
                            Обучение f = new Обучение(this);

                            f.pictureBox1.Image = поискСимволов.изображениеПрямоугольников.ToBitmap();
                            f.ShowDialog();
                        }
                        else*/
                        {
                            pictureBox2.Image = null;
                            pictureBox3.Image = null;
                            pictureBox1.Image = поискПрямоугольника.output.ToBitmap();
                            pictureBox3.Image = поискСимволов.изображениеПрямоугольников.ToBitmap();
                            pictureBox3.Refresh();
                            pictureBox2.Visible = true;
                            pictureBox2.Image = поискСимволов.output.ToBitmap();
                            pictureBox2.Refresh();
                            string str = "";
                            toolStripStatusLabel2.Text += "символы найдены за " + Convert.ToString((DateTime.Now - time).TotalSeconds) + "c";
                            foreach (IplImage po in поискСимволов.imageRectangle)
                            {
                                double min = 100000000000;
                                char c = ' ';
                                foreach (MatrixSymbol m in матрицыСимволов)
                                {
                                    double u = m.compare(po);
                                    if (min > u)
                                    {
                                        min = u;
                                        c = m.symbol;
                                    }
                                }
                                str += c;
                            }
                            label1.Text = str;
                            label1.Visible = true;
                        }
                    }
                }
            toolStripStatusLabel2.Text += "обработано за " + Convert.ToString((DateTime.Now - time).TotalSeconds) + "c";
        }

        private void saveEduvationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            XmlSerializer xml;
            FileStream stream;
            xml = new XmlSerializer(typeof(List<MatrixSymbol>));
            stream = new FileStream("Матрицы.xml", FileMode.Create, FileAccess.ReadWrite);
            xml.Serialize(stream, матрицыСимволов);
            stream.Close();
        }


        public void education(string text)
        {
            if (поискСимволов.coordinatesRectangle.Count == text.Length)
                for (int i = 0; i < text.Length; i++)
                    foreach (MatrixSymbol t in матрицыСимволов)
                        if (t.symbol == text[i]) t.add(поискСимволов.imageRectangle[i]);
        }

        private void videoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            /*SearchAndRecognition s = new SearchAndRecognition(настройкиПоискНомера, настройкиПоискСимволов, матрицыСимволов);

            openVideoDialog.ShowDialog();

            if (File.Exists(openVideoDialog.FileName))
            {
                CvCapture capture = Cv.CreateFileCapture(openVideoDialog.FileName);
                while (true)
                {
                    IplImage i = capture.QueryFrame();
                    if (i != null)
                    {
                        List<Number> l = s.go(new Image(i), обучетьToolStripMenuItem.Checked);
                        pictureBox1.Image = s.output.ToBitmap();
                         pictureBox1.Refresh();
                        if (l.Count > 0)
                        {
                            label1.Text = l[0].text;
                            label1.Refresh();
                            pictureBox2.Image = l[0].numeber.ToBitmap();
                            pictureBox3.Image = l[0].sybol.ToBitmap();
                            label1.Visible = true;
                            
                            pictureBox2.Refresh();
                            pictureBox3.Refresh();
                         
                            
                        }
                    }
                    else
                        break;
                }
            }*/
            openVideoDialog.ShowDialog();

            if (File.Exists(openVideoDialog.FileName))
            {
                capture = new Capture(openVideoDialog.FileName, настройкиПоискНомера, настройкиПоискСимволов, матрицыСимволов);
                timer1.Enabled = true;
                start.Visible = true;
             }
        }

        private void камераToolStripMenuItem_Click(object sender, EventArgs e)
        {
                capture = new Capture(0, настройкиПоискНомера, настройкиПоискСимволов, матрицыСимволов);
                timer1.Enabled = true;
                start.Visible = true;
                timer1.Interval = 1000 / Convert.ToInt32(toolStripTextBox1.Text);
            
        }

        private void открытьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            capture = new Capture(0, настройкиПоискНомера, настройкиПоискСимволов, матрицыСимволов);
            capture.go(false);
            motion = new Motion(capture.output);
            timer2.Enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (last == null)
                last = new List<Number>();
            List<Number>  del = new List<Number>();
            List<Number> l = capture.go(обучетьToolStripMenuItem.Checked, деткторДвиженияToolStripMenuItem.Checked);
            foreach (Number k in last)
                foreach (Number f in l)
                    if (k.text == f.text)
                        del.Add(f);
            foreach (Number k in del)
                l.Remove(k);
            
            foreach (Number k in l)
                        last.Add(k);

            
            if (capture.output != null)
            {
                pictureBox1.Image = capture.output.ToBitmap();
                pictureBox1.Refresh();
                if (l.Count > 0)
                {
                    foreach (Number k in l)
                        History.Add(k);

                    if (l[0].education == false)
                    {
                        
                            label1.Text = l[0].text;
                            label1.Refresh();
                            pictureBox2.Image = l[0].numeber.ToBitmap();
                            pictureBox3.Image = l[0].sybol.ToBitmap();
                            label1.Visible = true;
                            pictureBox2.Refresh();
                            pictureBox3.Refresh();
                        
                    }
                    else
                        timer1.Enabled = false;
                }
            }
            else
            {
                timer1.Enabled = false;
                start.Visible = false;
            }
            showHistory();
        }

        public void showHistory()
        {
            listBox1.Items.Clear();
            if (sh == null) sh = new List<int>();
            sh.Clear();
            for (int i = 0; i < History.Count; i++)
            {
                if ((monthCalendar1.SelectionStart<=History[i].time.Date) & (monthCalendar1.SelectionEnd>=History[i].time.Date))
                {
                    listBox1.Items.Add(History[i].time.Hour+":"+History[i].time.Minute+" "+History[i].text);
                    sh.Add(i);
                }
            }
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            timer1.Enabled = !timer1.Enabled;
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            IplImage i= capture.frame;
            if ( i!= null)
            {
                motion.search(i);
                pictureBox1.Image = motion.output.ToBitmap();
            }
      
        }

        private void toolStripTextBox1_Click(object sender, EventArgs e)
        {

        }

        private void сохранитьИсторияToolStripMenuItem_Click(object sender, EventArgs e)
        {
            XmlSerializer xml;
            FileStream stream;
            xml = new XmlSerializer(typeof(List<Number>));
            stream = new FileStream("История.xml", FileMode.Create, FileAccess.ReadWrite);
            xml.Serialize(stream, History);
            stream.Close();
        }

        private void monthCalendar1_DateChanged(object sender, DateRangeEventArgs e)
        {
            showHistory();
        }

        private void listBox1_DoubleClick(object sender, EventArgs e)
        {
            Info i = new Info(History[sh[listBox1.SelectedIndex]]);
            i.Show();
        }

    }
}
